﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Dotnet.Utils.Utility.EncryptUtil
{
    public static class SecurityUtil
    {
        private static string HashEncrypt(HashAlgorithm hashAlgorithm, string input, Encoding encoding)
        {
            byte[] result = hashAlgorithm.ComputeHash(encoding.GetBytes(input));
            return ToString(result);
        }

        private static bool VerifyHashValue(HashAlgorithm hashAlgorithm, string unhashedText, string hashedText, Encoding encoding)
        {
            return string.Equals(HashEncrypt(hashAlgorithm, unhashedText, encoding), hashedText, StringComparison.OrdinalIgnoreCase);
        }

        public static string Md5Hash(Stream stream)
        {
            if (stream.CanSeek)
            {
                stream.Position = 0L;
            }
            string result2;
            using (MD5 md = MD5.Create())
            {
                byte[] result = md.ComputeHash(stream);
                result2 = ToString(result);
            }
            return result2;
        }

        public static string Md5Hash(byte[] bytes)
        {
            string result2;
            using (MD5 md = MD5.Create())
            {
                byte[] result = md.ComputeHash(bytes);
                result2 = ToString(result);
            }
            return result2;
        }

        private static string ToString(byte[] result)
        {
            return BitConverter.ToString(result).Replace("-", string.Empty).ToLowerInvariant();
        }

        public static string Md5Encrypt(string input)
        {
            return Md5Encrypt(input, Encoding.UTF8);
        }

        public static string Md5Encrypt(string input, Encoding encoding)
        {
            return HashEncrypt(MD5.Create(), input, encoding);
        }

        public static bool Md5Verify(string input)
        {
            return Md5Verify(input, Encoding.UTF8);
        }

        public static bool Md5Verify(string input, Encoding encoding)
        {
            return VerifyHashValue(MD5.Create(), input, Md5Encrypt(input, encoding), encoding);
        }

        public static string Sha1Encrypt(string input)
        {
            return Sha1Encrypt(input, Encoding.UTF8);
        }

        public static string Sha1Encrypt(string input, Encoding encoding)
        {
            return HashEncrypt(SHA1.Create(), input, encoding);
        }

        public static bool Sha1Verify(string input)
        {
            return Sha1Verify(input, Encoding.UTF8);
        }

        public static bool Sha1Verify(string input, Encoding encoding)
        {
            return VerifyHashValue(SHA1.Create(), input, Sha1Encrypt(input, encoding), encoding);
        }

        public static string Sha256Encrypt(string input)
        {
            return Sha256Encrypt(input, Encoding.UTF8);
        }

        public static string Sha256Encrypt(string input, Encoding encoding)
        {
            return HashEncrypt(SHA256.Create(), input, encoding);
        }

        public static bool Sha256Verify(string input)
        {
            return Sha256Verify(input, Encoding.UTF8);
        }

        public static bool Sha256Verify(string input, Encoding encoding)
        {
            return VerifyHashValue(SHA256.Create(), input, Sha256Encrypt(input, encoding), encoding);
        }

        public static string Sha384Encrypt(string input)
        {
            return Sha384Encrypt(input, Encoding.UTF8);
        }

        public static string Sha384Encrypt(string input, Encoding encoding)
        {
            return HashEncrypt(SHA384.Create(), input, encoding);
        }

        public static bool Sha384Verify(string input)
        {
            return Sha384Verify(input, Encoding.UTF8);
        }

        public static bool Sha384Verify(string input, Encoding encoding)
        {
            return VerifyHashValue(SHA256.Create(), input, Sha384Encrypt(input, encoding), encoding);
        }

        public static string Sha512Encrypt(string input)
        {
            return Sha512Encrypt(input, Encoding.UTF8);
        }

        public static string Sha512Encrypt(string input, Encoding encoding)
        {
            return HashEncrypt(SHA512.Create(), input, encoding);
        }

        public static bool Sha512Verify(string input)
        {
            return Sha512Verify(input, Encoding.UTF8);
        }

        public static bool Sha512Verify(string input, Encoding encoding)
        {
            return VerifyHashValue(SHA512.Create(), input, Sha512Encrypt(input, encoding), encoding);
        }

        public static string DesEncrypt(string input, string key)
        {
            return DesEncrypt(input, key, Encoding.UTF8);
        }

        public static string DesEncrypt(string input, string key, Encoding encoding)
        {
            string result;
            try
            {
                byte[] bytes = encoding.GetBytes(key);
                DES des = DES.Create();
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.Zeros;
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    byte[] bytes2 = encoding.GetBytes(input);
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, des.CreateEncryptor(bytes, IvBytes), CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(bytes2, 0, bytes2.Length);
                        cryptoStream.FlushFinalBlock();
                    }
                    result = Convert.ToBase64String(memoryStream.ToArray());
                }
            }
            catch
            {
                result = input;
            }
            return result;
        }

        public static string DesDecrypt(string input, string key)
        {
            return DesDecrypt(input, key, Encoding.UTF8);
        }

        public static string DesDecrypt(string input, string key, Encoding encoding)
        {
            string result;
            try
            {
                byte[] bytes = encoding.GetBytes(key);
                DES des = DES.Create();
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.Zeros;
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    byte[] array = Convert.FromBase64String(input);
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, des.CreateDecryptor(bytes, IvBytes), CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(array, 0, array.Length);
                        cryptoStream.FlushFinalBlock();
                    }
                    result = encoding.GetString(memoryStream.ToArray());
                }
            }
            catch
            {
                result = input;
            }
            return result;
        }

        public static void RsaGenerateKeys(out string publicKey, out string privateKey)
        {
            using (RSACryptoServiceProvider rsacryptoServiceProvider = new RSACryptoServiceProvider())
            {
                publicKey = rsacryptoServiceProvider.ToXmlString(false);
                privateKey = rsacryptoServiceProvider.ToXmlString(true);
            }
        }

        public static string RsaEncrypt(string publickey, string content)
        {
            return RsaEncrypt(publickey, content, Encoding.UTF8);
        }

        public static string RsaEncrypt(string publickey, string content, Encoding encoding)
        {
            RSACryptoServiceProvider rsacryptoServiceProvider = new RSACryptoServiceProvider();
            rsacryptoServiceProvider.FromXmlString(publickey);
            byte[] inArray = rsacryptoServiceProvider.Encrypt(encoding.GetBytes(content), false);
            return Convert.ToBase64String(inArray);
        }

        public static string RsaDecrypt(string privatekey, string content)
        {
            return RsaDecrypt(privatekey, content, Encoding.UTF8);
        }

        public static string RsaDecrypt(string privatekey, string content, Encoding encoding)
        {
            RSACryptoServiceProvider rsacryptoServiceProvider = new RSACryptoServiceProvider();
            rsacryptoServiceProvider.FromXmlString(privatekey);
            byte[] bytes = rsacryptoServiceProvider.Decrypt(Convert.FromBase64String(content), false);
            return encoding.GetString(bytes);
        }

        private static readonly byte[] IvBytes = new byte[]
        {
            1,
            35,
            69,
            103,
            137,
            171,
            205,
            239
        };
    }
}